package com.gdkj.common.interceptor;

import cn.hutool.core.util.StrUtil;
import com.gdkj.common.BussCommonResponse;
import com.gdkj.common.LogicResult;
import com.gdkj.common.annotataion.JWTTokenAuth;
import com.gdkj.common.jwt.TokenData;
import com.gdkj.common.jwt.Tool;
import com.gdkj.constant.CodeConstants;
import com.gdkj.constant.CodeMessage;
import com.gdkj.constant.RedisConstant;
import com.xjgks.common.constant.HttpResultConstants;
import com.xjgks.common.response.HttpResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * token拦截器
 */
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {

    @Resource
    private Tool jwtTool;
    
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 只拦截方法
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        // 数据准备
        Method method = ((HandlerMethod) handler).getMethod();
        String jwtToken = request.getHeader("Authorization");
        String language = request.getHeader("language");
        if (language != null){
            request.setAttribute("language", language);
        }
        JWTTokenAuth jwtTokenAuth = method.getAnnotation(JWTTokenAuth.class);

        // 如果有数据则放入
        if (StrUtil.isNotEmpty(jwtToken)) {
            LogicResult authTokenResult = jwtTool.verifyToken(jwtToken);
            if (HttpResultConstants.FAIL_CODE.equals(authTokenResult.getCode())) {
                if(jwtTokenAuth == null){
                    return true;
                }
                HttpResult failResult = HttpResult.fail(100003,"token认证失败");
                BussCommonResponse.print(response, failResult);
                return false;
            }
            TokenData tokenData = (TokenData) authTokenResult.getData();
            // 5.校验redisKey
            String haveKey = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_TOKEN+tokenData.getUid());
            if (!request.getRequestURI().contains("sendCode") && !request.getRequestURI().contains("login") && !request.getRequestURI().contains("Login")){
                if(haveKey==null||!jwtToken.equals(haveKey)){
                    HttpResult failResult = HttpResult.fail(100003,"token认证失败");
                    BussCommonResponse.print(response, failResult);
                    return false;
                }
            }
            request.setAttribute("uid", tokenData.getUid());
            request.setAttribute("userLogin", tokenData.getUserLogin());
        }

        // 获取token认证注解
        if (jwtTokenAuth == null) {
            return true;
        }

        // token必传判断
        if (jwtTokenAuth.required() && StrUtil.isEmpty(jwtToken)) {
            HttpResult failResult = HttpResult.fail(100003,"token为必传参数");
            BussCommonResponse.print(response, failResult);
            return false;
        }

        return true;
    }
}
